package com.rabtman.common.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.Inflater;

public class ZipHelper {

  /**
   * zlib decompress 2 String
   */
  public static String decompressToStringForZlib(byte[] bytesToDecompress) {
    byte[] bytesDecompressed = decompressForZlib
        (
            bytesToDecompress
        );

    String returnValue = null;

    try {
      returnValue = new String
          (
              bytesDecompressed,
              0,
              bytesDecompressed.length,
              "UTF-8"
          );
    } catch (UnsupportedEncodingException uee) {
      uee.printStackTrace();
    }

    return returnValue;
  }


  /**
   * zlib decompress 2 byte
   */
  public static byte[] decompressForZlib(byte[] bytesToDecompress) {
    byte[] returnValues = null;

    Inflater inflater = new Inflater();

    int numberOfBytesToDecompress = bytesToDecompress.length;

    inflater.setInput
        (
            bytesToDecompress,
            0,
            numberOfBytesToDecompress
        );

    int bufferSizeInBytes = numberOfBytesToDecompress;

    int numberOfBytesDecompressedSoFar = 0;
    List<Byte> bytesDecompressedSoFar = new ArrayList<Byte>();

    try {
      while (inflater.needsInput() == false) {
        byte[] bytesDecompressedBuffer = new byte[bufferSizeInBytes];

        int numberOfBytesDecompressedThisTime = inflater.inflate
            (
                bytesDecompressedBuffer
            );

        numberOfBytesDecompressedSoFar += numberOfBytesDecompressedThisTime;

        for (int b = 0; b < numberOfBytesDecompressedThisTime; b++) {
          bytesDecompressedSoFar.add(bytesDecompressedBuffer[b]);
        }
      }

      returnValues = new byte[bytesDecompressedSoFar.size()];
      for (int b = 0; b < returnValues.length; b++) {
        returnValues[b] = (byte) (bytesDecompressedSoFar.get(b));
      }

    } catch (DataFormatException dfe) {
      dfe.printStackTrace();
    }

    inflater.end();

    return returnValues;
  }

  /**
   * zlib compress 2 byte
   */
  public static byte[] compressForZlib(byte[] bytesToCompress) {
    Deflater deflater = new Deflater();
    deflater.setInput(bytesToCompress);
    deflater.finish();

    byte[] bytesCompressed = new byte[Short.MAX_VALUE];

    int numberOfBytesAfterCompression = deflater.deflate(bytesCompressed);

    byte[] returnValues = new byte[numberOfBytesAfterCompression];

    System.arraycopy
        (
            bytesCompressed,
            0,
            returnValues,
            0,
            numberOfBytesAfterCompression
        );

    return returnValues;
  }

  /**
   * zlib compress 2 byte
   */
  public static byte[] compressForZlib(String stringToCompress) {
    byte[] returnValues = null;

    try {

      returnValues = compressForZlib
          (
              stringToCompress.getBytes("UTF-8")
          );
    } catch (UnsupportedEncodingException uee) {
      uee.printStackTrace();
    }

    return returnValues;
  }

  /**
   * gzip compress 2 byte
   */
  public static byte[] compressForGzip(String string) {
    ByteArrayOutputStream os = null;
    GZIPOutputStream gos = null;
    try {
      os = new ByteArrayOutputStream(string.length());
      gos = new GZIPOutputStream(os);
      gos.write(string.getBytes("UTF-8"));
      byte[] compressed = os.toByteArray();
      return compressed;
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      okhttp3.internal.Util.closeQuietly(gos);
      okhttp3.internal.Util.closeQuietly(os);
    }
    return null;
  }

  /**
   * gzip decompress 2 string
   */
  public static String decompressForGzip(byte[] compressed) {

    final int BUFFER_SIZE = compressed.length;
    GZIPInputStream gis = null;
    ByteArrayInputStream is = null;
    try {
      is = new ByteArrayInputStream(compressed);
      gis = new GZIPInputStream(is, BUFFER_SIZE);
      StringBuilder string = new StringBuilder();
      byte[] data = new byte[BUFFER_SIZE];
      int bytesRead;
      while ((bytesRead = gis.read(data)) != -1) {
        string.append(new String(data, 0, bytesRead, "UTF-8"));
      }
      return string.toString();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      okhttp3.internal.Util.closeQuietly(gis);
      okhttp3.internal.Util.closeQuietly(is);
    }
    return null;
  }
}
